package com.yuyou.fn.updater.handler;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.wens.mybatisplus.toolkit.IdWorker;
import com.google.common.base.Optional;
import com.google.common.cache.LoadingCache;
import com.yuyou.fn.common.database.event.EventHandler;
import com.yuyou.fn.common.database.event.IEventHandler;
import com.yuyou.fn.common.util.*;
import com.yuyou.fn.crm.entity.CrmStudentCommunicate;
import com.yuyou.fn.crm.service.ICrmStudentCommunicateService;
import com.yuyou.fn.crm.vo.CrmStudentCommunicateQueryVo;
import com.yuyou.fn.educational.entity.*;
import com.yuyou.fn.educational.service.*;
import com.yuyou.fn.platform.entity.BusTeam;
import com.yuyou.fn.platform.service.IBusTeamService;
import com.yuyou.fn.report.entity.MergeStudentRegDetail;
import com.yuyou.fn.report.entity.StudentRegDetail;
import com.yuyou.fn.report.service.IMergeStudentRegDetailService;
import com.yuyou.fn.report.service.IStudentRegDetailService;
import com.yuyou.fn.settlement.entity.NewPayRecord;
import com.yuyou.fn.settlement.service.INewPayRecordService;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;


import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import java.math.BigDecimal;

import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

@EventHandler(tables = {"yyfn.student_reg"})
@Component
public class StudentRegStateUpdater implements IEventHandler {

  //  private final static Logger log = LoggerFactory.getLogger(StudentRegStateUpdater.class);

    @Resource
    private IStudentRegService studentRegService;

    @Resource
    private ICourseClassService courseClassService;

    @Resource
    private IPeriodService periodService;

    @Resource
    private IStudentService studentService;

    @Resource
    private IBusTeamService busTeamService;

    @Resource
    private ITeacherService teacherService;


    @Resource
    private IStudentRegDetailService studentRegDetailService;


    @Resource
    private IClassLectureService classLectureService;

    @Resource
    private ICourseTemplateService courseTemplateService;

    @Resource
    private IExternalRegDetailService externalRegDetailService;

    @Resource
    private ICrmStudentCommunicateService crmStudentCommunicateService;

    @Resource
    private IMergeStudentRegDetailService mergeStudentRegDetailService;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private Redisson redisson;

    @Resource
    private INewPayRecordService newPayRecordService;

    @Resource
    private IPeriodGradeDateService periodGradeDateService;

    private final Logger log = LoggerFactory.getLogger(StudentRegStateUpdater.class);

    private LoadingCache<Long,Optional<CourseTemplate>> loadingCacheOfCourseTemplate ;
    private LoadingCache<Long,Optional<CourseClass>> loadingCacheOfCourseClass ;
    private LoadingCache<Long,Optional<Teacher>> teacherLoadingCache ;
    private LoadingCache<Long,Optional<Student>> studentLoadingCache ;
    private  LoadingCache<Long,Optional<Period>> periodLoadingCache ;
    @PostConstruct
    public void init(){

        this.loadingCacheOfCourseTemplate = CacheUtils.buildCache(courseTemplateService::findById);
        this.loadingCacheOfCourseClass = CacheUtils.buildCache(courseClassService::findById);
        this.teacherLoadingCache = CacheUtils.buildCache(teacherService::findById) ;
        this.studentLoadingCache = CacheUtils.buildCache(studentService::findById) ;
        this.periodLoadingCache =  CacheUtils.buildCache(periodService::findById) ;
    }


    private static String[] classColumns={"classId","className","courseTemplateId","gradeId","gradeName","subjectId","subjectName","lectureAmount","studyingFee","periodId","periodName","areaTeamId","areaTeamName","busTeamId","busTeamName","campusId","campusName","productId"};


    @Override
    public void insert(String tableName, JSONArray rowList) {
        build(tableName, rowList);
    }

    @Override
    public void update(String tableName, JSONArray rowList, Set<String> updateColumns) {
        build(tableName, rowList);
    }

    @Override
    public void delete(String tableName, JSONArray rowList) {

    }

    private void build(String tableName, JSONArray rowList) {
        for (int i = 0; i < rowList.size(); i++) {
            JSONObject row = rowList.getJSONObject(i);
            final StudentReg studentReg = row.toJavaObject(StudentReg.class);
            final StudentRegDetail studentRegDetail =studentRegDetailService.findById(studentReg.getRegId());


            /*报名信息发生变动（在读状态，咨询师，班主任），需刷新后面期数的在读信息，重新计算提成者*/
            Boolean regChange=false;
            if (studentReg.getRegStatus()!=0 && studentRegDetail!=null && (studentReg.getRegStatus()!=studentRegDetail.getRegStatus())){
                regChange=true;
            }
            if (studentRegDetail!=null){
                Long counselorId=studentReg.getCounselorId()==null?0l:studentReg.getCounselorId();
                Long seniorId=studentReg.getSeniorId()==null?0:studentReg.getSeniorId();
                Long checkCounselorId = studentRegDetail.getCounselorId()==null?0l:studentRegDetail.getCounselorId();
                Long checkSeniorId = studentRegDetail.getSeniorId()==null?0l:studentRegDetail.getSeniorId();
                if (!counselorId.equals(checkCounselorId) || !seniorId.equals(checkSeniorId)){
                    regChange=true;
                }
            }


            Threads.dispatch(new Runnable() {
                @Override
                public void run() {
                    updateStudentLastCampus(studentReg);
                }
            });


            try{
                fillOrUpdateStudentRegDetail(studentReg,regChange);
            }catch (Exception e){
                log.error("更新report regId："+studentReg.getRegId()+"失败",e);
            }
            /*本来放在另外 一个update，由于需对比student_reg 和student_reg_detail的班主任是否发生更换*/
            Threads.dispatch(new Runnable() {
                @Override
                public void run() {
                    saveOrUpdateCrmCommunicate(studentReg, studentRegDetail);
                }
            });
        }
    }



    private void fillOrUpdateStudentRegDetail(StudentReg studentReg,Boolean regChange) throws ExecutionException {

        Period nowPeriod = periodLoadingCache.get(studentReg.getPeriodId()).get();
        CourseClass courseClass=loadingCacheOfCourseClass.get(studentReg.getClassId()).get();
        Student student=studentLoadingCache.get(studentReg.getStudentId()).get();
        CourseTemplate courseTemplate = loadingCacheOfCourseTemplate.get(courseClass.getCourseTemplateId()).get();
        StudentRegDetail studentRegDetail =toStudentRegDetail(nowPeriod,studentReg,courseClass,student,courseTemplate);
        this.fillStudentState(student, studentReg, nowPeriod, courseClass, studentRegDetail);

        try{
            studentRegDetailService.insert(studentRegDetail);
        }catch (Exception e){
            studentRegDetailService.updateSelectiveById(studentRegDetail);
        }
        Integer studentState=studentRegDetail.getStudentState();
        Threads.dispatch(new Runnable() {
            @Override
            public void run() {
                updateMergeStudentRegDetail(nowPeriod,studentReg, courseClass,  student,  courseTemplate, studentState);
            }
        });

        if (regChange){
            Threads.dispatch(new Runnable() {
                @Override
                public void run() {
                    List<Period> afterPeriodList=periodService.findNextByPeriodId(studentReg.getPeriodId(),2);
                    List<Long> periodIds = BeanUtils.toList(afterPeriodList, "periodId");
                    List<StudentReg> studentRegList = studentRegService.findByPeriods(periodIds, studentReg.getStudentId(), 0);

                    if (Utils.checkListNotEmpty(studentRegList)){
                        for (StudentReg studentReg1:studentRegList){
                            try {
                                fillOrUpdateStudentRegDetail(studentReg1,false);
                            }catch (Exception e){
                                log.error("更新report regId："+studentReg.getRegId()+"失败",e);
                            }
                        }
                    }
                }
            });
        }

    }
    private StudentRegDetail toStudentRegDetail(Period period, StudentReg studentReg, CourseClass courseClass, Student student, CourseTemplate courseTemplate){
        StudentRegDetail studentRegDetail =new StudentRegDetail();
        studentRegDetail.setPayTime(studentReg.getLastPayTime());
        studentRegDetail.setRegId(studentReg.getRegId());
        studentRegDetail.setClassId(studentReg.getClassId());
        studentRegDetail.setOperator(studentReg.getOperator());
        studentRegDetail.setClassName(studentReg.getClassName());
        studentRegDetail.setPeriodId(studentReg.getPeriodId());
        studentRegDetail.setPeriodName(period.getPeriodName());
        studentRegDetail.setAreaTeamId(courseClass.getAreaTeamId());
        studentRegDetail.setBusTeamId(courseClass.getBusTeamId());
        studentRegDetail.setBusTeamName(courseClass.getBusTeamName());
        studentRegDetail.setGradeId(courseClass.getGradeId());
        studentRegDetail.setGradeName(courseClass.getGradeName());
        studentRegDetail.setSubjectId(courseClass.getSubjectId());
        studentRegDetail.setSubjectName(courseClass.getSubjectName());
        studentRegDetail.setSeniorId(studentReg.getSeniorId());
        studentRegDetail.setCourseOrderId(studentReg.getCourseOrderId());
        studentRegDetail.setSeniorName(studentReg.getSeniorName());
        studentRegDetail.setStudentId(studentReg.getStudentId());
        studentRegDetail.setStudentName(student.getName());
        studentRegDetail.setCreateTime(studentReg.getCreateTime());
        studentRegDetail.setUpdateTime(studentReg.getUpdateTime());
        studentRegDetail.setLectureNum(studentReg.getEndAmount() - studentReg.getStartAmount()+1);
        studentRegDetail.setOperatorId(studentReg.getOperatorId());
        studentRegDetail.setCounselorId(studentReg.getCounselorId());
        studentRegDetail.setCounselorName(studentReg.getCounselorName());
        studentRegDetail.setStartAmount(studentReg.getStartAmount());
        studentRegDetail.setEndAmount(studentReg.getEndAmount());
        studentRegDetail.setTotalAmount(studentReg.getTotalAmount());
        studentRegDetail.setPayAmount(studentReg.getPayAmount());
        studentRegDetail.setRegStatus(studentReg.getRegStatus());
        studentRegDetail.setChargingStatus(studentReg.getChargingStatus());
        studentRegDetail.setSrcTotalAmount(studentReg.getSrcTotalAmount());
        studentRegDetail.setStudentNo(student.getStudentNo());
        studentRegDetail.setStudentGradeName(student.getGradeName());
        studentRegDetail.setStudentPhoneNo(student.getPhoneNo());
        studentRegDetail.setRegFrom(studentReg.getRegFrom());
        studentRegDetail.setClassType(courseClass.getClassType());
        studentRegDetail.setStartCourseTime(courseClass.getStartCourseTime());
        studentRegDetail.setCampusId(courseClass.getCampusId());
        studentRegDetail.setCampusName(courseClass.getCampusName());
        studentRegDetail.setRoomId(courseClass.getRoomId());
        studentRegDetail.setRoomName(courseClass.getRoomName());
        studentRegDetail.setSegmentNo(courseClass.getSegmentNo());
        studentRegDetail.setTeacherId(courseClass.getTeacherId());
        studentRegDetail.setJobNature(courseClass.getJobNature());
        studentRegDetail.setTeacherName(courseClass.getTeacherName());
        studentRegDetail.setInitStartAmount(studentReg.getInitStartAmount());
        studentRegDetail.setInitEndAmount(studentReg.getInitEndAmount());
        studentRegDetail.setRefundAmount(studentReg.getRefundAmount());
        studentRegDetail.setStudyingTime(courseClass.getStudyingTime());
        studentRegDetail.setCourseId(courseClass.getCourseTemplateId());
        studentRegDetail.setCourseName(courseTemplate.getCourseName());
        studentRegDetail.setProductId(courseClass.getProductId());
        studentRegDetail.setProductName(courseTemplate.getProductName());
        studentRegDetail.setClassNo(courseClass.getClassNo());
        studentRegDetail.setAreaTeamName(courseClass.getAreaTeamName());

        studentRegDetail.setDiscountReason(this.findDiscountReason(studentReg));

        return studentRegDetail;
    }



    /*判断生源类型*/
    void  fillStudentState(Student student,StudentReg studentReg,Period period,CourseClass courseClass,StudentRegDetail StudentRegDetail){
        Integer ifNewStudent = this.checkIfNewStudent(period, courseClass.getAreaTeamId(), studentReg.getStudentId());
        if (ifNewStudent==1){
            StudentRegDetail.setStudentState(0);//新生
        }else {
            List<Period> previousPeriodList=periodService.findPreviousByPeriodId(period.getPeriodId(),2);
            List<Long> previousPeriodIds=BeanUtils.toList(previousPeriodList,"periodId");
            List<StudentReg> studentRegList = studentRegService.findByPeriods(previousPeriodIds, studentReg.getStudentId(), 0);
            Long  externalNum=externalRegDetailService.countPrevious(student.getStudentId(),previousPeriodIds,courseClass.getAreaTeamId(),0);
            if ((studentRegList != null && studentRegList.size() > 0) || externalNum>0L ) {
                StudentRegDetail.setStudentState(2);//续读生
            } else {
                StudentRegDetail.setStudentState(1);//老生
            }

        }


    }



    private void updateStudentLastCampus(StudentReg studentReg){
        if (studentReg.getRegStatus()==0){
            Student student=studentService.findById(studentReg.getStudentId());
            if (student.getLastRegTime()==null || student.getLastRegTime().getTime()<studentReg.getCreateTime().getTime()){
                CourseClass courseClass=courseClassService.findById(studentReg.getClassId(),"classId","campusId","campusName");
                Student update=new Student();
                update.setStudentId(student.getStudentId());
                update.setLastRegTime(studentReg.getCreateTime());
                update.setLastRegCampusId(courseClass.getCampusId());
                update.setLastRegCampusName(courseClass.getCampusName());
                studentService.updateSelectiveById(update);
            }
        }

    }


    private String findDiscountReason(StudentReg studentReg){
        if(studentReg.getDiscountDetail() != null ){
            String[] spilts  = studentReg.getDiscountDetail().split(",");
            List<String> discountNames = new ArrayList<>(spilts.length);
            for(String s : spilts){
                discountNames.add(s.split("\\|")[0]);
            }
            return StringUtils.join(discountNames,",");
        }
        return null ;
    }





    private Integer checkIfNewStudent(Period period, Long areaTeamId, Long studentId) {
        List<Period> periods = periodService.findListBeforePeriodId(areaTeamId, period.getPeriodId());
        List<Long> periodIds = BeanUtils.toList(periods, "periodId");
        Long num = studentRegService.countPrevious(periodIds, studentId, areaTeamId, 0);

        Long externalNum =externalRegDetailService.countPrevious(studentId,periodIds,areaTeamId,0);
        num=num+externalNum;
        if (num == 0L) {
            return 1;
        } else {
            return 0;
        }
    }



    private void saveOrUpdateCrmCommunicate(StudentReg studentReg,StudentRegDetail originStudentRegDetail){
        Long studentId=studentReg.getStudentId();
        Long busTeamId=studentReg.getBusTeamId();
        Long periodId=studentReg.getPeriodId();
        Long areaTeamId=studentReg.getAreaTeamId();

        Long seniorId=studentReg.getSeniorId();
        CrmStudentCommunicateQueryVo crmStudentCommunicateQueryVo=new CrmStudentCommunicateQueryVo();
        crmStudentCommunicateQueryVo.setStudentId(studentId);
        crmStudentCommunicateQueryVo.setBusTeamId(busTeamId);
        crmStudentCommunicateQueryVo.setPeriodId(periodId);
        StudentRegDetail StudentRegDetail =studentRegDetailService.findById(studentReg.getRegId());
        if (seniorId!=null){
            this.dealSeniorCommunicate(seniorId,areaTeamId,studentId,busTeamId,periodId, StudentRegDetail.getSegmentNo(), StudentRegDetail.getStudentState(), StudentRegDetail.getGradeId());
        }
        if (seniorId!=null && originStudentRegDetail !=null &&  originStudentRegDetail.getSeniorId()!=null && !seniorId.equals(originStudentRegDetail.getSeniorId())){
            this.dealSeniorCommunicate(originStudentRegDetail.getSeniorId(),areaTeamId,studentId,busTeamId,periodId, originStudentRegDetail.getSegmentNo(), originStudentRegDetail.getStudentState(), originStudentRegDetail.getGradeId());
        }
    }

    private void dealSeniorCommunicate(Long seniorId,Long areaTeamId,Long studentId,Long busTeamId,Long periodId,Integer segmentNo,Integer studentState,Long gradeId){
        if (seniorId==null || areaTeamId==null || studentId==null || busTeamId==null || periodId==null){
            return;
        }
        CrmStudentCommunicateQueryVo crmStudentCommunicateQueryVo=new CrmStudentCommunicateQueryVo();
        crmStudentCommunicateQueryVo.setStudentId(studentId);
        crmStudentCommunicateQueryVo.setBusTeamId(busTeamId);
        crmStudentCommunicateQueryVo.setPeriodId(periodId);
        crmStudentCommunicateQueryVo.setSeniorId(seniorId);
        crmStudentCommunicateQueryVo.setSegmentNo(segmentNo);
        crmStudentCommunicateQueryVo.setStudentState(studentState);
        crmStudentCommunicateQueryVo.setGradeId(gradeId);
        CrmStudentCommunicate crmStudentCommunicate =crmStudentCommunicateService.findByQueryVo(crmStudentCommunicateQueryVo);
        Long seniorStudentRegCount=studentRegService.countBySeniorStudentRegs(seniorId,studentId,periodId,busTeamId);
        Integer regNum= seniorStudentRegCount.intValue();
        if (crmStudentCommunicate !=null){
            CrmStudentCommunicate update=new CrmStudentCommunicate();
            update.setStudentCommunicateId(crmStudentCommunicate.getStudentCommunicateId());
            update.setRegNum(regNum);
            update.setUpdateTime(TimeUtils.now());
            crmStudentCommunicateService.updateSelectiveById(update);
        }else {
            BusTeam busTeam=busTeamService.findById(busTeamId);
            Student  student=studentService.findById(studentId);
            Teacher teacher=teacherService.findById(seniorId);
            Period period=periodService.findById(periodId);
            CrmStudentCommunicate save=new CrmStudentCommunicate();
            save.setRegNum(regNum);
            save.setBusTeamId(busTeamId);
            save.setBusTeamName(busTeam.getName());
            save.setAreaTeamId(areaTeamId);
            save.setPeriodId(periodId);
            save.setPeriodName(period.getPeriodName());
            save.setStudentName(student.getName());
            save.setStudentPhoneNo(student.getPhoneNo());
            save.setStudentNo(student.getStudentNo());

            save.setSegmentNo(segmentNo);
            save.setStudentState(studentState);
            save.setGradeId(gradeId);


            save.setSeniorId(seniorId);
            save.setSeniorName(teacher.getTeacherName());
            save.setSeniorBusTeamId(teacher.getBusTeamId());
            save.setSeniorBusTeamName(teacher.getBusTeamName());
            save.setStudentId(studentId);
            save.setCommunicateNum(0);
            save.setCommunicateState(0);
            save.setUpdateTime(TimeUtils.now());
            save.setCreateTime(TimeUtils.now());
            save.setSchool(student.getSchool());
            save.setFocusOn(0);
            crmStudentCommunicateService.insert(save);
        }
    }

    private void updateMergeStudentRegDetail(Period period, StudentReg studentReg, CourseClass courseClass, Student student, CourseTemplate courseTemplate,Integer studentState){
        RLock lock = redisson.getLock(String.format("studentIdClassId:%s", studentReg.getStudentId()+"_"+courseClass.getClassId() ));
        lock.lock();
        try {
              /*创建时间排序*/
            String recordStudentRegMaxUpdateTime=(String) redisTemplate.opsForHash().get("recordStudentRegMaxUpdateTime",studentReg.getStudentId()+"_"+studentReg.getClassId());
            if (StringUtils.isNotEmpty(recordStudentRegMaxUpdateTime) && studentReg.getUpdateTime().getTime()<Long.parseLong(recordStudentRegMaxUpdateTime)){
                return;
            }
            List<StudentReg> studentRegList=studentRegService.findRegByClassIdStudentId(courseClass.getClassId(),student.getStudentId(),Arrays.asList(0,3));
            if (Utils.isEmpty(studentRegList)){
                mergeStudentRegDetailService.deleteByStudentIdClassId(studentReg.getStudentId(),courseClass.getClassId());
            }else if (Utils.checkListNotEmpty(studentRegList)){
                Boolean insertState=false;
                MergeStudentRegDetail check =mergeStudentRegDetailService.findByStudentIdClassId(studentReg.getStudentId(),courseClass.getClassId());
                MergeStudentRegDetail mergeStudentRegDetail=new MergeStudentRegDetail();
                if (check==null){
                    mergeStudentRegDetail.setRegId(IdWorker.getId());
                    insertState=true;
                }else {
                    mergeStudentRegDetail.setRegId(check.getRegId());
                }

                Integer lectureNum=0;
                BigDecimal totalAmount=BigDecimal.ZERO;
                BigDecimal payAmount=BigDecimal.ZERO;
                BigDecimal refundAmount=BigDecimal.ZERO;
                BigDecimal srcTotalAmount=BigDecimal.ZERO;

                Set<Integer> regStatusSet=new HashSet<>();
                Set<Integer> chargingStatusSet=new HashSet<>();
                mergeStudentRegDetail.setClassId(studentReg.getClassId());
                mergeStudentRegDetail.setClassName(studentReg.getClassName());
                mergeStudentRegDetail.setPeriodId(studentReg.getPeriodId());
                mergeStudentRegDetail.setPeriodName(period.getPeriodName());
                mergeStudentRegDetail.setAreaTeamId(courseClass.getAreaTeamId());
                mergeStudentRegDetail.setBusTeamId(courseClass.getBusTeamId());
                mergeStudentRegDetail.setBusTeamName(courseClass.getBusTeamName());
                mergeStudentRegDetail.setGradeId(courseClass.getGradeId());
                mergeStudentRegDetail.setGradeName(courseClass.getGradeName());
                mergeStudentRegDetail.setSubjectId(courseClass.getSubjectId());
                mergeStudentRegDetail.setSubjectName(courseClass.getSubjectName());
                mergeStudentRegDetail.setStudentId(studentReg.getStudentId());
                mergeStudentRegDetail.setStudentName(studentReg.getStudentName());
                Long maxUpdateTime=0L;
                for (int i=0;i<studentRegList.size();i++){

                    StudentReg one=studentRegList.get(i);
                    if (maxUpdateTime<one.getUpdateTime().getTime()){
                        maxUpdateTime=one.getUpdateTime().getTime();
                        mergeStudentRegDetail.setUpdateTime(one.getUpdateTime());
                    }

                    regStatusSet.add(one.getRegStatus());

                    if(one.getRegStatus()==0){
                        lectureNum+=(one.getEndAmount() - one.getStartAmount()+1);
                        chargingStatusSet.add(one.getChargingStatus());
                    }
                    totalAmount=totalAmount.add(one.getTotalAmount()==null?BigDecimal.ZERO:one.getTotalAmount());

                    payAmount=payAmount.add(one.getPayAmount()==null?BigDecimal.ZERO:one.getPayAmount());
                    refundAmount=refundAmount.add(one.getRefundAmount()==null?BigDecimal.ZERO:one.getRefundAmount());
                    srcTotalAmount=srcTotalAmount.add(one.getSrcTotalAmount()==null?BigDecimal.ZERO:one.getSrcTotalAmount());

                    if (mergeStudentRegDetail.getRegFrom()==null ){
                        mergeStudentRegDetail.setRegFrom(one.getRegFrom());
                    }

                    if (mergeStudentRegDetail.getSeniorId()==null && one.getRegStatus()==0){
                        mergeStudentRegDetail.setSeniorId(one.getSeniorId());
                        mergeStudentRegDetail.setSeniorName(one.getSeniorName());
                    }
                    if (mergeStudentRegDetail.getCounselorId()==null && one.getRegStatus()==0){
                        mergeStudentRegDetail.setCounselorId(one.getCounselorId());
                        mergeStudentRegDetail.setCounselorName(one.getCounselorName());
                    }

                    if (mergeStudentRegDetail.getPayTime()==null && one.getRegStatus()==0){
                        mergeStudentRegDetail.setPayTime(one.getLastPayTime());
                    }
                    if (mergeStudentRegDetail.getCreateTime()==null  && (one.getRegStatus()==0 || i==studentRegList.size()-1)){
                        mergeStudentRegDetail.setCreateTime(one.getCreateTime());
                    }

                }

                if (mergeStudentRegDetail.getPayTime()==null){
                    mergeStudentRegDetail.setPayTime(studentRegList.get(studentRegList.size()-1).getLastPayTime());
                }

                mergeStudentRegDetail.setClassType(courseClass.getClassType());
                mergeStudentRegDetail.setStartCourseTime(courseClass.getStartCourseTime());
                mergeStudentRegDetail.setCampusId(courseClass.getCampusId());
                mergeStudentRegDetail.setCampusName(courseClass.getCampusName());
                mergeStudentRegDetail.setRoomId(courseClass.getRoomId());
                mergeStudentRegDetail.setRoomName(courseClass.getRoomName());
                mergeStudentRegDetail.setSegmentNo(courseClass.getSegmentNo());
                mergeStudentRegDetail.setTeacherId(courseClass.getTeacherId());
                mergeStudentRegDetail.setJobNature(courseClass.getJobNature());
                mergeStudentRegDetail.setTeacherName(courseClass.getTeacherName());
                mergeStudentRegDetail.setStudyingTime(courseClass.getStudyingTime());
                mergeStudentRegDetail.setCourseId(courseClass.getCourseTemplateId());
                mergeStudentRegDetail.setCourseName(courseTemplate.getCourseName());
                mergeStudentRegDetail.setProductId(courseClass.getProductId());
                mergeStudentRegDetail.setProductName(courseTemplate.getProductName());
                mergeStudentRegDetail.setClassNo(courseClass.getClassNo());
                mergeStudentRegDetail.setAreaTeamName(courseClass.getAreaTeamName());
                mergeStudentRegDetail.setLocation(student.getLocation());
                mergeStudentRegDetail.setAddress(student.getAddress());
                mergeStudentRegDetail.setStudentNo(student.getStudentNo());
                mergeStudentRegDetail.setStudentGradeName(student.getGradeName());
                mergeStudentRegDetail.setStudentPhoneNo(student.getPhoneNo());

                mergeStudentRegDetail.setLectureNum(lectureNum);
                mergeStudentRegDetail.setTotalAmount(totalAmount);
                mergeStudentRegDetail.setPayAmount(payAmount);
                mergeStudentRegDetail.setSrcTotalAmount(srcTotalAmount);

                mergeStudentRegDetail.setRefundAmount(refundAmount);
                mergeStudentRegDetail.setStudentState(studentState);

                if (regStatusSet.contains(0)){
                    mergeStudentRegDetail.setRegStatus(0);
                }else {
                    mergeStudentRegDetail.setRegStatus(regStatusSet.iterator().next());
                }
                if (chargingStatusSet.size()>0){
                    if (chargingStatusSet.contains(1)){
                        mergeStudentRegDetail.setChargingStatus(1);
                    }else if (chargingStatusSet.contains(0)){
                        if (chargingStatusSet.contains(2)){
                            mergeStudentRegDetail.setChargingStatus(1);
                        }else {
                            mergeStudentRegDetail.setChargingStatus(0);
                        }
                    }else if (chargingStatusSet.contains(2)){
                        mergeStudentRegDetail.setChargingStatus(2);
                    }
                }else {
                    mergeStudentRegDetail.setChargingStatus(studentRegList.get(0).getChargingStatus());
                }

                /*全退后，计算不出新的咨询师 班主任，需保留原先的咨询师班主任*/
                if (mergeStudentRegDetail.getCounselorId()==null &&  check!=null){
                    mergeStudentRegDetail.setCounselorId(check.getCounselorId());
                    mergeStudentRegDetail.setCounselorName(check.getCounselorName());
                }

                if (mergeStudentRegDetail.getSeniorId()==null &&  check!=null){
                    mergeStudentRegDetail.setSeniorId(check.getSeniorId());
                    mergeStudentRegDetail.setSeniorName(check.getSeniorName());
                }

                mergeStudentRegDetail.setFirstPayTime(this.getFirstPayTime(studentReg.getCourseOrderId()));



                List<Period> previousPeriodList=periodService.findPreviousByPeriodId(period.getPeriodId(),2);
                Map<Integer, Period> periodNoMap = BeanUtils.toMap(previousPeriodList, "periodNo");
                List<Long> previousPeriodIds=BeanUtils.toList(previousPeriodList,"periodId");
                List<StudentReg> previousStudentRegList = studentRegService.findByPeriods(previousPeriodIds, studentReg.getStudentId(), 0);
                Period lastPeriod=periodNoMap.get(period.getPeriodNo()-1);
                Period firstPeriod=periodNoMap.get(period.getPeriodNo()-2);

                List<String> bonusPeriodPersonIds=this.findBonusPeriodPersonIds(studentState,mergeStudentRegDetail,studentReg,previousStudentRegList,courseClass,lastPeriod,firstPeriod);
                List<Long> bonusClassIds=this.findBonusClassIds(studentReg,previousStudentRegList,courseClass,lastPeriod,firstPeriod);




                bonusPeriodPersonIds=Utils.removeDuplicate(bonusPeriodPersonIds);
                bonusClassIds=Utils.removeDuplicate(bonusClassIds);
                mergeStudentRegDetail.setBonusPeriodPersonIds(StringUtils.join(bonusPeriodPersonIds,","));
                mergeStudentRegDetail.setBonusClassIds(StringUtils.join(bonusClassIds,","));
                if (insertState){
                    mergeStudentRegDetailService.insert(mergeStudentRegDetail);
                }else {
                    mergeStudentRegDetailService.updateSelectiveById(mergeStudentRegDetail);
                }
                redisTemplate.opsForHash().put("recordStudentRegMaxUpdateTime",studentReg.getStudentId()+"_"+studentReg.getClassId(),maxUpdateTime.toString());
            }
        }finally {
            lock.unlock();
        }


    }

    private Date getFirstPayTime(Long courseOrderId){
        NewPayRecord newPayRecord=newPayRecordService.findFirstPayByBusOrderId(courseOrderId);
        if (newPayRecord!=null){
            return newPayRecord.getCreateTime();
        }
        return null;
    }
    /*新老生提成者算本期和咨询师,续读生按最小讲次上课时间与缴费时间做对比*/
    private List<String> findBonusPeriodPersonIds(Integer studentState,MergeStudentRegDetail mergeStudentRegDetail,StudentReg studentReg,List<StudentReg> previousStudentRegList,CourseClass courseClass,Period lastPeriod,Period firstPeriod){
        List<String> bonusPeriodPersonIds=new ArrayList<>();
        if ((studentState==1 || studentState==0) && mergeStudentRegDetail.getCounselorId()!=null){
            Teacher teacher=teacherService.findById(mergeStudentRegDetail.getCounselorId());
            if (teacher!=null){
                bonusPeriodPersonIds.add(mergeStudentRegDetail.getPeriodId()+"_"+mergeStudentRegDetail.getCounselorId());
            }
        }else {
            List<StudentReg> seniorRegList = previousStudentRegList.stream().filter(item -> item.getSeniorId() != null).collect(Collectors.toList());
            Map<Long, List<StudentReg>> seniorRegMap = BeanUtils.toGroup(seniorRegList, "seniorId");

            for (Map.Entry<Long,List<StudentReg>> entry:seniorRegMap.entrySet()){
                List<StudentReg> oneSeniorReg=entry.getValue();
                Map<Long, List<StudentReg>> periodSeniorMap = BeanUtils.toGroup(oneSeniorReg, "periodId");
                if (periodSeniorMap.size()==1){
                    bonusPeriodPersonIds.add(oneSeniorReg.get(0).getPeriodId()+"_"+entry.getKey());
                }else if (mergeStudentRegDetail.getFirstPayTime()!=null){

                    List<StudentReg> onePeriodRegList=periodSeniorMap.get(lastPeriod.getPeriodId());
                    onePeriodRegList.sort(new Comparator<StudentReg>() {
                        @Override
                        public int compare(StudentReg o1, StudentReg o2) {
                            return o1.getStartAmount().compareTo(o2.getStartAmount());
                        }
                    });
                    Integer firstStartAmount=onePeriodRegList.get(0).getStartAmount();
                    ClassLecture classLecture=classLectureService.findClassLectureByClassIdLectureNo(onePeriodRegList.get(0).getClassId(),firstStartAmount);
                    Date date=Utils.parseDate(Utils.formatDate(classLecture.getClassDate(),"yyyy-MM-dd")+" "+classLecture.getStartTime(),"yyyy-MM-dd HH:mm");

                    if (mergeStudentRegDetail.getFirstPayTime().before(date) || mergeStudentRegDetail.getFirstPayTime().equals(date)){
                        bonusPeriodPersonIds.add(firstPeriod.getPeriodId()+"_"+entry.getKey());
                    }else {
                        bonusPeriodPersonIds.add(lastPeriod.getPeriodId()+"_"+entry.getKey());
                    }
                }
            }
        }
        return Utils.removeDuplicate(bonusPeriodPersonIds);
    }
    /*根据前期，前前期 相应年级的开课日计算*/
    private List<Long> findBonusClassIds(StudentReg studentReg,List<StudentReg> previousStudentRegList,CourseClass courseClass,Period lastPeriod,Period firstPeriod){
        List<Long> bonusClassIds=new ArrayList<>();
        List<Long> classIds = Utils.removeDuplicate(BeanUtils.toList(previousStudentRegList, "classId"));
        List<CourseClass> courseClassList=courseClassService.findByIds(classIds,CourseClass.BASE_FIELDS);
        courseClassList=courseClassList.stream().filter(item->item.getSubjectId().equals(courseClass.getSubjectId())).collect(Collectors.toList());
        Map<Long, CourseClass> courseClassMap = BeanUtils.toMap(courseClassList, "classId");
        List<StudentReg> sameSubjectRegList = previousStudentRegList.stream().filter(item->courseClassMap.containsKey(item.getClassId())).collect(Collectors.toList());

        Map<Long, List<StudentReg>> periodSameSubjectMap = BeanUtils.toGroup(sameSubjectRegList, "periodId");
        if (periodSameSubjectMap.size() == 1) {
            bonusClassIds.addAll(Utils.removeDuplicate(BeanUtils.toList(sameSubjectRegList, "classId")));
        } else if (periodSameSubjectMap.size() == 2) {
            List<StudentReg> studentRegList = periodSameSubjectMap.get(lastPeriod.getPeriodId());
            List<Long> regClassIds = BeanUtils.toList(studentRegList, "classId");
            Long maxGradeId=null;
            for (Long classId:regClassIds){
                CourseClass temp=courseClassMap.get(classId);
                if (temp!=null && (maxGradeId==null || maxGradeId.intValue()<temp.getGradeId().intValue())){
                    maxGradeId=temp.getGradeId();
                }
            }
            PeriodGradeDate periodGradeDate = periodGradeDateService.findByPeriodIdGradeId(lastPeriod.getPeriodId(), maxGradeId);
            if (periodGradeDate != null) {
                if (studentReg.getCreateTime().before(periodGradeDate.getPeriodGradeDate()) || studentReg.getCreateTime().equals(periodGradeDate.getPeriodGradeDate())) {
                    bonusClassIds.addAll(BeanUtils.toList(periodSameSubjectMap.get(firstPeriod.getPeriodId()), "classId"));
                } else {
                    bonusClassIds.addAll(BeanUtils.toList(periodSameSubjectMap.get(lastPeriod.getPeriodId()), "classId"));
                }
            }
        }

        return Utils.removeDuplicate(bonusClassIds);
    }
}
